package com.srmt.document.feishu.internal.writer;

import com.lark.oapi.service.docx.v1.model.*;
import com.srmt.document.exception.CellException;
import com.srmt.document.feishu.internal.core.BlockContext;
import com.srmt.document.feishu.internal.table.TableOperationStrategy;
import com.srmt.document.feishu.internal.table.TableStrategyFactory;
import com.srmt.document.feishu.internal.table.TableWriteStrategy;
import com.srmt.document.feishu.internal.table.model.TableContext;
import com.srmt.document.feishu.internal.util.BlockContextHelper;
import com.srmt.feishu.client.FeishuClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 单元格操作服务
 * 从FeishuContentWriter中抽取的单元格相关操作
 * 
 * @author srmt
 * @since 1.1.0
 */
public class CellOperationService {
    
    private static final Logger logger = LoggerFactory.getLogger(CellOperationService.class);
    
    private final FeishuClient client;
    private final TableStrategyFactory strategyFactory;
    
    public CellOperationService(FeishuClient client) {
        this.client = client;
        this.strategyFactory = TableStrategyFactory.create(client);
    }
    
    /**
     * 设置单个单元格内容
     */
    public void setCellContent(String docId, String tableAnchor, int row, int col, String content) 
            throws CellException {
        logger.debug("在锚点 '{}' 的表格中设置单元格 [{}, {}] 的内容", row, col, tableAnchor);
        
        try {
            performSetCellContent(docId, tableAnchor, row, col, content);
        } catch (CellException e) {
            throw e;
        } catch (Exception e) {
            throw new CellException("设置单元格内容失败: " + e.getMessage());
        }
    }
    
    private void performSetCellContent(String docId, String tableAnchor, int row, int col, String content) 
            throws Exception {
        // 创建上下文
        BlockContext context = new BlockContext(client, docId);
        
        // 查找表格
        Block tableBlock = BlockContextHelper.findAndValidateTable(context, tableAnchor);
        
        // 直接使用策略更新单元格内容
        TableContext tableContext = new TableContext(docId, context, tableBlock);
        TableWriteStrategy writeStrategy = strategyFactory.getWriteStrategy(tableBlock);
        writeStrategy.updateCellContentByIndex(tableContext, row, col, content);
        
        logger.info("单元格 [{}, {}] 内容更新成功", row, col);
    }
    
    /**
     * 批量设置单元格内容
     */
    public void setCellsContent(String docId, String tableAnchor, int startRow, int startCol, 
                               List<List<String>> content) throws CellException {
        logger.debug("在锚点 '{}' 的表格中设置 {} x {} 个单元格的内容", 
                    content.size(), content.isEmpty() ? 0 : content.get(0).size(), tableAnchor);
        
        try {
            performSetCellsContent(docId, tableAnchor, startRow, startCol, content);
        } catch (CellException e) {
            throw e;
        } catch (Exception e) {
            throw new CellException("设置多个单元格内容失败: " + e.getMessage());
        }
    }
    
    private void performSetCellsContent(String docId, String tableAnchor, int startRow, int startCol,
                                       List<List<String>> content) throws Exception {
        // 创建上下文
        BlockContext context = new BlockContext(client, docId);
        
        // 查找表格
        Block tableBlock = BlockContextHelper.findAndValidateTable(context, tableAnchor);
        
        // 构建基于行列索引的更新映射
        Map<int[], String> cellUpdates = buildCellUpdatesMap(startRow, startCol, content);
        
        // 使用策略进行批量更新
        TableContext tableContext = new TableContext(docId, context, tableBlock);
        TableWriteStrategy writeStrategy = strategyFactory.getWriteStrategy(tableBlock);
        writeStrategy.batchUpdateCellsByIndex(tableContext, cellUpdates);
        
        logger.info("已更新表格中的 {} 个单元格", cellUpdates.size());
    }
    
    /**
     * 合并单元格
     */
    public void mergeCells(String docId, String tableAnchor, int startRow, int startCol, 
                          int endRow, int endCol) throws CellException {
        logger.debug("在锚点 '{}' 的表格中合并单元格 [{},{} 到 {},{}]", 
                    startRow, startCol, endRow, endCol, tableAnchor);
        
        try {
            performMergeCells(docId, tableAnchor, startRow, startCol, endRow, endCol);
        } catch (CellException e) {
            throw e;
        } catch (Exception e) {
            throw new CellException("合并单元格失败: " + e.getMessage());
        }
    }
    
    private void performMergeCells(String docId, String tableAnchor, int startRow, int startCol,
                                  int endRow, int endCol) throws Exception {
        // 创建上下文
        BlockContext context = new BlockContext(client, docId);
        
        // 查找表格
        Block tableBlock = BlockContextHelper.findAndValidateTable(context, tableAnchor);
        
        // 创建表格上下文
        TableContext tableContext = new TableContext(docId, context, tableBlock);
        
        // 获取合适的策略并执行合并操作
        TableOperationStrategy strategy = strategyFactory.getStrategy(tableBlock);
        strategy.mergeCells(tableContext, startRow, startCol, endRow, endCol);
        
        logger.info("已合并单元格 [{},{} 到 {},{}]", startRow, startCol, endRow, endCol);
    }
    
    /**
     * 替换合并单元格旁边的内容
     */
    public void replaceCellsNextToMergedCell(String docId, String tableAnchor, String cellText, 
                                            List<String> values) throws CellException {
        logger.debug("替换表格中包含文本 '{}' 的合并单元格旁边的单元格", cellText);
        
        try {
            performReplaceCellsNextToMergedCell(docId, tableAnchor, cellText, values);
        } catch (CellException e) {
            throw e;
        } catch (Exception e) {
            throw new CellException("替换单元格失败: " + e.getMessage());
        }
    }
    
    private void performReplaceCellsNextToMergedCell(String docId, String tableAnchor, String cellText,
                                                    List<String> values) throws Exception {
        // 创建上下文
        BlockContext context = new BlockContext(client, docId);
        
        // 查找表格
        Block tableBlock = context.findTableAfterAnchor(tableAnchor);
        if (tableBlock == null) {
            throw new CellException("锚点后未找到表格: " + tableAnchor);
        }
        
        // 创建表格上下文并使用策略模式
        TableContext tableContext = new TableContext(docId, context, tableBlock);
        TableOperationStrategy strategy = strategyFactory.getStrategy(tableBlock);
        
        // 获取表格维度
        int[] dimensions = strategy.getTableDimensions(tableContext);
        
        // 查找包含指定文本的合并单元格
        int targetRow = -1;
        int targetCol = -1;
        int rowSpan = 1;
        int colSpan = 1;
        boolean found = false;
        
        // 使用1-based索引遍历表格
        for (int row = 1; row <= dimensions[0] && !found; row++) {
            for (int col = 1; col <= dimensions[1] && !found; col++) {
                String content = strategy.getCellContent(tableContext, row, col);
                if (content != null && content.contains(cellText)) {
                    targetRow = row;
                    targetCol = col;
                    found = true;
                    
                    // 检查是否是合并单元格并获取其跨度
                    if (strategy.isMergedCell(tableContext, row, col)) {
                        int[] span = strategy.getCellSpan(tableContext, row, col);
                        rowSpan = span[0];
                        colSpan = span[1];
                        logger.debug("在[{}, {}]位置找到合并单元格,跨度[{}, {}],内容为'{}'",
                                   row, col, rowSpan, colSpan, cellText);
                    } else {
                        logger.debug("在[{}, {}]位置找到普通单元格,内容为'{}'", row, col, cellText);
                    }
                }
            }
        }
        
        if (!found) {
            throw new CellException("表格中未找到包含文本的单元格");
        }
        
        // 替换合并单元格右侧相邻列的单元格内容
        // 右侧列的位置是 targetCol + colSpan
        int targetColumn = targetCol + colSpan;
        
        if (targetColumn > dimensions[1]) {
            throw new CellException("合并单元格右侧不存在列");
        }
        
        // 替换的行数应该与合并单元格的行跨度一致
        int replacedCount = 0;
        int valuesToReplace = Math.min(values.size(), rowSpan);
        
        for (int i = 0; i < valuesToReplace; i++) {
            int currentRow = targetRow + i; // 从合并单元格的起始行开始
            if (currentRow <= dimensions[0]) {
                // 使用setCellContent方法更新单元格（1-based索引）
                setCellContent(docId, tableAnchor, currentRow, targetColumn, values.get(i));
                replacedCount++;
                logger.debug("替换d cell [{}, {}] with value '{}'", 
                           currentRow, targetColumn, values.get(i));
            } else {
                logger.warn("行 {} exceeds table height {}, stopping replacement", 
                          currentRow, dimensions[0]);
                break;
            }
        }
        
        if (replacedCount == 0) {
            throw new CellException("未替换任何单元格 - 目标单元格可能位于最右侧位置");
        }
        
        logger.info("成功替换合并单元格相邻的{}个单元格", replacedCount);
    }
    
    // ========== 辅助方法 ==========
    
    /**
     * 构建单元格更新映射
     */
    private Map<int[], String> buildCellUpdatesMap(int startRow, int startCol, 
                                                  List<List<String>> content) {
        Map<int[], String> cellUpdates = new HashMap<>();
        
        for (int i = 0; i < content.size(); i++) {
            List<String> rowValues = content.get(i);
            int row = startRow + i;
            
            for (int j = 0; j < rowValues.size(); j++) {
                int col = startCol + j;
                String value = rowValues.get(j);
                
                if (value != null) {
                    cellUpdates.put(new int[]{row, col}, value);
                }
            }
        }
        
        return cellUpdates;
    }
}